package jp.anago_dev.takarush_helper.location;

import java.util.List;

import android.app.AlarmManager;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;

/**
 * 位置情報履歴から最適なものを探索します。
 * 
 * @author anago_dev
 * 
 */
public class LastKnownLocationFinder {

    /** コンテキスト */
    private final Context mContext;

    /** {@link LocationManager} */
    private final LocationManager mLocationManager;

    private final Criteria mCriteria;

    /** 位置情報履歴のしきい精度(meter) */
    private static final int ACCURCY_THRESHOLD = 500;

    /** 位置情報履歴のしきい時間 */
    private static final long TIME_THRESHOLD = AlarmManager.INTERVAL_FIFTEEN_MINUTES;

    /**
     * コンストラクタ
     * 
     * @param context
     */
    public LastKnownLocationFinder(final Context context) {

        mContext = context;
        mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        // Criteriaの構築
        mCriteria = new Criteria();
        mCriteria.setAccuracy(Criteria.ACCURACY_LOW);

    }

    /**
     * 最適な位置情報履歴を取得します。<br/>
     * 履歴がなければnullを返します。
     * 
     * @return
     */
    public Location getLastBestLocation() {

        // 現在時間からMAX_TIME(15分)前
        final long minTime = System.currentTimeMillis() - TIME_THRESHOLD;

        Location bestResult = null;
        float bestAccuracy = Float.MAX_VALUE;
        long bestTime = Long.MIN_VALUE;

        // 全ての位置プロバイダから履歴を取得
        final List<String> matchingProviders = mLocationManager.getAllProviders();
        for (String provider : matchingProviders) {
            Location location = mLocationManager.getLastKnownLocation(provider);
            if (location != null) {
                float accuracy = location.getAccuracy();
                long time = location.getTime();

                // 時間と精度が高い場合
                if ((time > minTime && accuracy < bestAccuracy)) {
                    bestResult = location;
                    bestAccuracy = accuracy;
                    bestTime = time;
                }
            }
        }

        // 時間または精度がしきい値より低ければ履歴なしと判断
        if (bestTime < minTime || bestAccuracy > ACCURCY_THRESHOLD) {
            bestResult = null;
        }

        return bestResult;
    }
}
